package com.example.artwindow.tool;

import com.example.artwindow.constants.HttpCodeEnum;
import com.example.artwindow.exception.UnauthorizedException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;

import javax.crypto.SecretKey;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;


public class JwtTool {
    public static final int ACCESS_EXPIRE = 60*60*12;
    /**
     * 加密算法
     */
    private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
    /**
     * 私钥 / 生成签名的时候使用的秘钥secret，一般可以从本地配置文件中读取，切记这个秘钥不能外露，只在服务端使用，在任何场景都不应该流露出去。
     * 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
     * 应该大于等于 256位(长度32及以上的字符串)，并且是随机的字符串
     */
    private final static String SECRET = "1RMmDij8Btvb10CZZhowq5xFVT9Lr3iRQveyNkH6Q9j7ow48Gx16ccPtIKPv1TWxdyICj8mBJ65aaghF4X73FCrlhceVttjpCi8f";
    /**
     * 秘钥实例
     */
    public static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());
    /**
     * jwt签发者
     */
    private final static String JWT_ISS = "EiEi";
    /**
     * jwt主题
     */
    private final static String SUBJECT = "用户登录";


    /**
     * 创建jwt
     *
     */
    public static String createToken(Long userId) {

        //生成JWT
        return  Jwts.builder()
                //设置Header
                .header()
                .add("typ", "JWT")
                .add("alg", "HS256")
                .and()
                //设置payload
                .claim("userId", userId)
                //令牌id
                .id(UUID.randomUUID().toString())
                //过期日期
                .expiration(Date.from(Instant.now().plusSeconds(ACCESS_EXPIRE)))
                //签发日期
                .issuedAt(new Date())
                //主题
                .subject(SUBJECT)
                //签发者
                .issuer(JWT_ISS)
                //签名
                .signWith(KEY,ALGORITHM)
                .compact();
    }

    /**
     * 解析token
     *
     * @param token token
     * @return 解析刷新token得到的用户信息
     */
    public static Long parseToken(String token) throws UnauthorizedException {
        // 1.校验token是否为空
        if (token == null) {
            throw new UnauthorizedException(HttpCodeEnum.ERR_NOT_LOGIN);
        }
        try {
            return Jwts.parser()
                    .verifyWith(KEY)
                    .build()
                    .parseSignedClaims(token).getPayload().get("userId",Long.class);
        }catch (RuntimeException e)
        {
            throw new UnauthorizedException(HttpCodeEnum.ERR_LOGIN);
        }

    }
}